package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.article.dto.*;
import com.heima.article.entity.*;
import com.heima.article.es.ApArticleSearch;
import com.heima.article.es.ArticleSearchRepository;
import com.heima.article.feign.BehaviorFeign;
import com.heima.article.feign.MediaFeign;
import com.heima.article.feign.UserFeign;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.IApArticleContentService;
import com.heima.article.service.IApArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.service.IApAuthorService;
import com.heima.article.service.IApCollectionService;
import com.heima.article.task.ArticleTasks;
import com.heima.common.dto.PageResponseResult;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.util.AppThreadLocalUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 文章信息表，存储已发布的文章 服务实现类
 * </p>
 *
 * @author mcm
 * @since 2021-11-11
 */
@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements IApArticleService {


    @Autowired
    private IApArticleContentService contentService;

    @Autowired
    private ArticleTasks tasks;

    @Autowired
    private ArticleSearchRepository articleSearchRepository;

    @Override
    public ResponseResult<Long> saveArticle(ArticleDto dto) {
        ApArticle article = new ApArticle();
        BeanUtils.copyProperties(dto, article);
        // 判断是否有id
        // 如果id为空,需要新增
        if (dto.getId() == null) {
            article.setCreatedTime(new Date());
            // 保存文章
            this.save(article);
            // 保存文章内容
            ApArticleContent content = new ApArticleContent();
            content.setArticleId(article.getId());
            content.setContent(dto.getContent());
            contentService.save(content);

            // 保存文章的同时创建es索引
            ApArticleSearch articleSearch = new ApArticleSearch();
            BeanUtils.copyProperties(article, articleSearch);
            articleSearchRepository.save(articleSearch);

            // 异步调用服务进行静态页面的生成
            tasks.createHtml(article, dto.getContent());
            return ResponseResult.okResult(article.getId());
        }
        // id不为空,更新文章
        this.updateById(article);
        // 更新文章内容
        LambdaUpdateWrapper<ApArticleContent> update = new LambdaUpdateWrapper<>();
        update.eq(ApArticleContent::getArticleId, dto.getId());
        update.set(ApArticleContent::getContent, dto.getContent());
        contentService.update(update);
        return ResponseResult.okResult(dto.getId());
    }

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 加载文章列表
     *
     * @param dto
     * @param type 0 最新  1 更多
     * @return
     */
    @Override
    public ResponseResult load(ArticleHomeDto dto, int type) {

        // 判断是否是首页加载数据,如果是首页的话,先从redis中查询数据
        if (dto.getLoaddir() == 1) {
            // 先从redis中查询数据,按照分值从大到小排序
            String key = "hot_article_first_page_" + dto.getChannelId();
            long start = 0;
            long end = dto.getSize() - 1;
            Set<String> strings = redisTemplate.opsForZSet().reverseRange(key, start, end);
            List<ApArticle> articles = new ArrayList<>();
            for (String string : strings) {
                ApArticle article = JSON.parseObject(string, ApArticle.class);
                articles.add(article);
            }
            if (articles.size() >= dto.getSize()) {
                return ResponseResult.okResult(articles);
            }
        }

        // 条件查询
        LambdaQueryWrapper<ApArticle> query = new LambdaQueryWrapper<>();
        // 根据频道id查询
        if (dto.getChannelId() != null && dto.getChannelId() != 0) {
            query.eq(ApArticle::getChannelId, dto.getChannelId());
        }
        // 判断加载最新文章,查询比传递的最大时间更大的文章
        if (type == 0) {
            query.gt(ApArticle::getPublishTime, dto.getMaxTime());
        }
        // 判断加载更多文章,查询比传递的最小时间更小的文章
        if (type == 1) {
            query.lt(ApArticle::getPublishTime, dto.getMinTime());
        }
        // 文章是已上架 没有删除
        query.eq(ApArticle::getIsDown, false);
        query.eq(ApArticle::getIsDelete, false);
        // 按照发布时间倒序排列
        query.orderByDesc(ApArticle::getPublishTime);
        // 分页查询,默认显示10条,前端会传递
        IPage<ApArticle> page = new Page<>(1, dto.getSize());
        IPage<ApArticle> iPage = this.page(page, query);
        return ResponseResult.okResult(iPage.getRecords());
    }

    @Override
    public ResponseResult loadArticleInfo(ArticleInfoDto dto) {
        // 根据文章id查询文章
        ApArticle apArticle = this.getById(dto.getArticleId());
        // 判断文章是已上架未删除状态
        if (apArticle.getIsDown() || apArticle.getIsDelete()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 查询文章内容
        LambdaQueryWrapper<ApArticleContent> query = new LambdaQueryWrapper<>();
        query.eq(ApArticleContent::getArticleId, dto.getArticleId());
        ApArticleContent content = contentService.getOne(query);
        // 定义返回的结果
        Map<String, Object> map = new HashMap<>();
        map.put("config", apArticle);
        map.put("content", content);
        return ResponseResult.okResult(map);
    }

    @Autowired
    private BehaviorFeign behaviorFeign;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private IApCollectionService collectionService;

    @Override
    public ResponseResult collect(CollectionBehaviorDto dto) {
        // 获取当前登录的用户
        User user = AppThreadLocalUtil.get();
        EntryDto entryDto = new EntryDto();
        entryDto.setEquipmentId(dto.getEquipmentId());
        if (user != null) {
            entryDto.setUserId(user.getUserId());
        }
        // 远程查询行为实体
        ResponseResult<ApBehaviorEntry> entryResponseResult = behaviorFeign.getEntry(entryDto);
        if (entryResponseResult != null && entryResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            ApBehaviorEntry entry = entryResponseResult.getData();
            // 构建收藏记录
            ApCollection collection = new ApCollection();
            collection.setEntryId(entry.getId());
            collection.setArticleId(dto.getArticleId());
            collection.setCollectionTime(new Date());
            // 判断是否已经有记录
            LambdaQueryWrapper<ApCollection> query = new LambdaQueryWrapper<>();
            query.eq(ApCollection::getArticleId, dto.getArticleId());
            query.eq(ApCollection::getEntryId, entry.getId());
            ApCollection one = collectionService.getOne(query);
            if (one == null) {
                if (dto.getOperation() == 0) {
                    collectionService.save(collection);
                }
            } else {
                if (dto.getOperation() == 1) {
                    collectionService.removeById(one.getId());
                }
            }
        }
        return ResponseResult.okResult();
    }

    @Autowired
    private IApAuthorService authorService;

    @Override
    public ResponseResult loadArticleBehavior(ArticleInfoDto dto) {

        Boolean isFollow = false;
        Boolean isLike = false;
        Boolean isUnLike = false;
        Boolean isCollection = false;

        // 获取当前登录的用户
        User user = AppThreadLocalUtil.get();
        EntryDto entryDto = new EntryDto();
        entryDto.setEquipmentId(dto.getEquipmentId());
        if (user != null) {
            entryDto.setUserId(user.getUserId());
        }
        ResponseResult<ApBehaviorEntry> entryResponseResult = behaviorFeign.getEntry(entryDto);
        if (entryResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            ApBehaviorEntry entry = entryResponseResult.getData();
            // 查询点赞记录
            LikesBehaviorDto likeDto = new LikesBehaviorDto();
            likeDto.setEntryId(entry.getId());
            likeDto.setArticleId(dto.getArticleId());
            ResponseResult<ApLikesBehavior> behaviorResponseResult = behaviorFeign.getLikes(likeDto);
            if (behaviorResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
                ApLikesBehavior likesBehavior = behaviorResponseResult.getData();
                if (likesBehavior != null && likesBehavior.getOperation() == 0) {
                    isLike = true;
                }
            }
            // 查询不喜欢记录
            UnLikesBehaviorDto unLikeDto = new UnLikesBehaviorDto();
            unLikeDto.setEntryId(entry.getId());
            unLikeDto.setArticleId(dto.getArticleId());
            ResponseResult<ApUnlikesBehavior> unlikesBehaviorResponseResult = behaviorFeign.getUnlikes(unLikeDto);
            if (unlikesBehaviorResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
                ApUnlikesBehavior unlikesBehavior = unlikesBehaviorResponseResult.getData();
                if (unlikesBehavior != null && unlikesBehavior.getType() == 0) {
                    isUnLike = true;
                }
            }

            // 查询收藏记录
            LambdaQueryWrapper<ApCollection> query = new LambdaQueryWrapper<>();
            query.eq(ApCollection::getEntryId, entry.getId());
            query.eq(ApCollection::getArticleId, dto.getArticleId());
            ApCollection collection = collectionService.getOne(query);
            if (collection != null) {
                isCollection = true;
            }
        }

        // 查询作者信息
        ApAuthor apAuthor = authorService.getById(dto.getAuthorId());
        // 查询用户微服务
        FollowBehaviorDto followDto = new FollowBehaviorDto();
        followDto.setUserId(user.getUserId());
        followDto.setFollowId(apAuthor.getUserId());
        ResponseResult<ApUserFollow> followResponseResult = userFeign.getFollow(followDto);
        if (followResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            ApUserFollow userFollow = followResponseResult.getData();
            if (userFollow != null) {
                isFollow = true;
            }
        }


        // 定义返回的结果
        Map<String, Boolean> map = new HashMap<>();
        map.put("isfollow", isFollow);
        map.put("islike", isLike);
        map.put("isunlike", isUnLike);
        map.put("iscollection", isCollection);
        return ResponseResult.okResult(map);
    }

    /**
     * 图文统计数量
     * @param dto
     * @return
     */
    public ResponseResult newsDimension(NewsDimensionDto dto) {
        SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd");
        Date start;
        Date end;
        try {
            //开始时间
            String beginDate = dto.getBeginDate();
            start = simple.parse(beginDate);
            //结束时间
            String endDate = dto.getEndDate();
            Date end1 = simple.parse(endDate);
            Calendar cal = Calendar.getInstance();
            cal.setTime(end1);
            cal.add(cal.DATE,1);
            end = cal.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            //解析失败
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //查询条件
        LambdaQueryWrapper<ApArticle> query = Wrappers.lambdaQuery(ApArticle.class);
        query.lt(ApArticle::getPublishTime,end).ge(ApArticle::getPublishTime,start).eq(ApArticle::getIsDown,false).eq(ApArticle::getIsDelete,false);
        List<ApArticle> articleList = this.list(query);
        Integer likesNum=0;
        Integer collectNum=0;
        if(articleList ==null){
            return ResponseResult.okResult();
        }
        //文章发布量
        Integer publishNum = articleList.size();
        //总点赞数  ||  总收藏数
        for (ApArticle article : articleList) {
            likesNum+=article.getLikes();
            collectNum+=article.getCollection();
        }
        CountInfo countInfo = new CountInfo();
        countInfo.setPublishNum(publishNum);;
        countInfo.setLikesNum(likesNum);
        countInfo.setCollectNum(collectNum);
        return ResponseResult.okResult(countInfo);
    }

    /**
     * 图文统计信息
     * @param dto
     * @return
     */
    public ResponseResult getNewsPageStatistics(NewsDimensionDto dto) {
        SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd");
        Date start;
        Date end;
        try {
            //开始时间
            String beginDate = dto.getBeginDate();
            start = simple.parse(beginDate);
            //结束时间
            String endDate = dto.getEndDate();
            Date end1 = simple.parse(endDate);
            Calendar cal = Calendar.getInstance();
            cal.setTime(end1);
            cal.add(cal.DATE,1);
            end = cal.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            //解析失败
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //查询条件
        LambdaQueryWrapper<ApArticle> query = Wrappers.lambdaQuery(ApArticle.class);
        query.lt(ApArticle::getPublishTime,end).ge(ApArticle::getPublishTime,start).eq(ApArticle::getIsDown,false).eq(ApArticle::getIsDelete,false);
        query.orderByDesc(ApArticle::getPublishTime);
        //分页
        IPage<ApArticle> iPage = new Page(dto.getPage(), dto.getSize());
        IPage<ApArticle> page = this.page(iPage, query);
        ArrayList<ArticleInfo> articleInfos = new ArrayList<>();
        List<ApArticle> apArticleList = page.getRecords();
        for (ApArticle article : apArticleList) {
            ArticleInfo articleInfo = new ArticleInfo();
            articleInfo.setId(article.getId());
            articleInfo.setTitle(article.getTitle());
            articleInfo.setLikes(article.getLikes());
            articleInfo.setCollection(article.getCollection());
            articleInfo.setComment(article.getComment());
            articleInfo.setViews(article.getViews());
            articleInfos.add(articleInfo);
        }
        return new PageResponseResult(dto.getPage(),dto.getSize(),page.getTotal(),articleInfos);
    }
    @Override
    public ResponseResult loadComments(CommentDto dto) {
        User user = AppThreadLocalUtil.get();
        Integer wmUserId = user.getUserId();
        WmUser wmUser = mediaFeign.findWmUser(wmUserId);
        Integer apAuthorId = wmUser.getApAuthorId();
        System.out.println("作者"+apAuthorId);
        String beginDate = dto.getBeginDate();
        String endDate = dto.getEndDate();
        Long page = dto.getPage();
        Integer size = dto.getSize();
        QueryWrapper<ApArticle> query = new QueryWrapper();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            if(beginDate!=null){
                Date begin = simpleDateFormat.parse(beginDate);
                System.out.println(beginDate);
                query.ge("publish_time",begin);
            }
            if(endDate!=null){
                Date end = simpleDateFormat.parse(endDate);
                System.out.println("结束时间"+ endDate);
                query.le("publish_time",end);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        query.eq("author_id",apAuthorId);
        query.orderByDesc("publish_time");
        IPage pages = new Page(page, size);
        IPage iPage = apArticleService.page(pages, query);
        return new PageResponseResult(page,size,iPage.getTotal(),iPage.getRecords());
    }

    @Override
    public ResponseResult updateComment(CommentStatus dto) {
        //Long articleId = dto.getArticleId();
        //ApArticle article = apArticleService.getById(articleId);
        /*UpdateWrapper<ApArticle> update = new UpdateWrapper<>();
        update.eq("id",dto.getArticleId());*/
        LambdaUpdateWrapper<ApArticle> update = new LambdaUpdateWrapper<>();
        update.eq(ApArticle::getId,dto.getArticleId());
        update.set(ApArticle::getIsComment,dto.getOperation()== 1 ? true : false);
        apArticleService.update(update);
        return ResponseResult.okResult();
    }

    @Autowired
    private IApArticleService apArticleService;

    @Autowired
    private MediaFeign mediaFeign;
}
